package com.example.jdbc.login;

import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Scanner;

/**
 * 模拟用户登录
 * SQL注入问题解决
 * 解决SQL注入的关键是什么？
 *  用户提供的信息中即使含有 SQL语句的关键字，但是这些关键字并没有参与编译，不起作用。
 * Statement vs PreparedStatement
 *  Statement 存在SQL注入问题，PreparedStatment 解决了SQL注入
 *  Statement是编译一次执行一次，PreparedStatment是编译一次，执行N次，PreparedStatment效率较高一些
 *  PreparedStatment会在编译器做类型的安全检查
 *
 * 综上所述：PreparedStatment 使用较多，只有极少数情况下使用Statement
 * 什么情况下必须使用Statement？
 *  业务方面要求必须支持SQL注入的时候
 *  Statement支持SQL注入，凡是业务方面要求是需要进行SQL语句拼接的，必须使用Statement
 */
public class LoginDemo2 {
    public static void main(String[] args) {
        Map<String, String> userInfo = initUI();
        boolean loginSuccess = login(userInfo);
    }

    private static boolean login(Map<String, String> userInfo) {
        boolean loginSuccess = false;
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://192.168.31.92:3306/muser", "root", "123456");
            String sql = " select * from muser where username = ? and password = ? ";
            ps = conn.prepareStatement(sql);
            ps.setString(1, userInfo.get("username"));
            ps.setString(2, userInfo.get("password"));
            rs = ps.executeQuery(sql);
            if (rs.next()) {
                loginSuccess = true;
                System.out.println("login successfully");
                return loginSuccess;
            } else {
                System.out.println("login failed");
                return loginSuccess;
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (Objects.nonNull(rs)) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
            if (Objects.nonNull(ps)) {
                try {
                    ps.close();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
            if (Objects.nonNull(conn)) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return loginSuccess;
    }

    private static Map<String, String> initUI() {
        Scanner s = new Scanner(System.in);
        System.out.print("用户名： ");
        String username = s.nextLine();
        System.out.print("密码：");
        String password = s.nextLine();
        Map<String,String> userInfo = new HashMap<>();
        userInfo.put("username", username);
        userInfo.put("password", password);
        return userInfo;
    }


}
